package com.xiaoh.dormitoryrepairreportbackend.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaoh.dormitoryrepairreportbackend.annotation.RequireRole;
import com.xiaoh.dormitoryrepairreportbackend.common.BaseResponse;
import com.xiaoh.dormitoryrepairreportbackend.common.ErrorCode;
import com.xiaoh.dormitoryrepairreportbackend.constant.UserConstant;
import com.xiaoh.dormitoryrepairreportbackend.exception.BusinessException;
import com.xiaoh.dormitoryrepairreportbackend.model.dto.common.PageResponse;
import com.xiaoh.dormitoryrepairreportbackend.model.dto.common.UpdateRequest;
import com.xiaoh.dormitoryrepairreportbackend.model.dto.user.*;
import com.xiaoh.dormitoryrepairreportbackend.model.entity.GeneralUser;
import com.xiaoh.dormitoryrepairreportbackend.model.entity.UserAdmin;
import com.xiaoh.dormitoryrepairreportbackend.model.entity.UserMaintenance;
import com.xiaoh.dormitoryrepairreportbackend.model.entity.UserStudent;
import com.xiaoh.dormitoryrepairreportbackend.service.GeneralUserService;
import com.xiaoh.dormitoryrepairreportbackend.service.UserAdminService;
import com.xiaoh.dormitoryrepairreportbackend.service.UserMaintenanceService;
import com.xiaoh.dormitoryrepairreportbackend.service.UserStudentService;
import com.xiaoh.dormitoryrepairreportbackend.utils.QueryUtils;
import com.xiaoh.dormitoryrepairreportbackend.utils.UserConverter;
import com.xiaoh.dormitoryrepairreportbackend.utils.UserHolder;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 用户接口
 */
@RestController
@RequestMapping("/user")
@Slf4j
@Tag(name = "用户管理", description = "用户相关接口")
public class GeneralUserController {

    @Resource
    private GeneralUserService generalUserService;

    @Resource
    private UserStudentService userStudentService;

    @Resource
    private UserMaintenanceService userMaintenanceService;

    @Resource
    private UserAdminService userAdminService;

    /**
     * 用户注册
     */
    @PostMapping("/register")
    @Operation(summary = "用户注册", description = "用户注册接口，仅管理员可用")
    @RequireRole(UserConstant.UserType.ADMIN)
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Long> userRegister(@Valid @RequestBody UserRegisterRequest userRegisterRequest) {
        if (userRegisterRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String accountName = userRegisterRequest.getAccountName();
        String password = userRegisterRequest.getPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        String email = userRegisterRequest.getEmail();
        String phoneNumber = userRegisterRequest.getPhoneNumber();
        Integer userType = userRegisterRequest.getUserType();
        String dormitoryName = userRegisterRequest.getDormitoryName();

        if (StrUtil.hasBlank(accountName, password, checkPassword, email, phoneNumber)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        if (userType == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户类型不能为空");
        }
        if (!password.equals(checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        }
        if (UserConstant.UserType.STUDENT == userType && StrUtil.isBlank(dormitoryName)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "学生用户必须填写宿舍地址");
        }

        GeneralUser user = new GeneralUser();
        BeanUtils.copyProperties(userRegisterRequest, user);
        Long userId = generalUserService.userRegister(user);

        // 根据用户类型创建扩展信息
        if (userType == UserConstant.UserType.STUDENT) {
            UserStudent userStudent = new UserStudent();
            userStudent.setUserId(userId);
            userStudent.setDormitoryName(dormitoryName);
            userStudentService.save(userStudent);
        } else if (userType == UserConstant.UserType.MAINTENANCE) {
            UserMaintenance userMaintenance = new UserMaintenance();
            userMaintenance.setUserId(userId);
            userMaintenanceService.save(userMaintenance);
        } else if (userType == UserConstant.UserType.ADMIN) {
            UserAdmin userAdmin = new UserAdmin();
            userAdmin.setUserId(userId);
            userAdminService.save(userAdmin);
        }

        return BaseResponse.success(userId);
    }

    /**
     * 用户登录
     */
    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "用户登录接口")
    public BaseResponse<UserResponse> userLogin(@Valid @RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
        if (userLoginRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String accountName = userLoginRequest.getAccountName();
        String password = userLoginRequest.getPassword();
        GeneralUser user = generalUserService.userLogin(accountName, password);
        request.getSession().setAttribute(UserConstant.USER_LOGIN_STATE, user);
        return BaseResponse.success(UserConverter.toUserResponse(user));
    }

    /**
     * 用户注销
     */
    @PostMapping("/logout")
    @Operation(summary = "用户注销", description = "用户注销接口")
    public BaseResponse<Boolean> userLogout(HttpServletRequest request) {
        request.getSession().removeAttribute(UserConstant.USER_LOGIN_STATE);
        return BaseResponse.success(true);
    }

    /**
     * 获取当前登录用户
     */
    @PostMapping("/get/login")
    @Operation(summary = "获取当前登录用户", description = "获取当前登录用户信息")
    public BaseResponse<UserResponse> getLoginUser(HttpServletRequest request) {
        Object userObj = request.getSession().getAttribute(UserConstant.USER_LOGIN_STATE);
        GeneralUser currentUser = (GeneralUser) userObj;
        if (currentUser == null || currentUser.getId() == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        long userId = currentUser.getId();
        GeneralUser user = generalUserService.getById(userId);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        return BaseResponse.success(UserConverter.toUserResponse(user));
    }

    /**
     * 分页获取用户列表
     * 使用游标分页保持性能，同时返回完整分页信息
     */
    @PostMapping("/list/page")
    @Operation(summary = "分页获取用户列表", description = "使用游标分页获取用户列表，返回完整分页信息（总记录数、总页数等）")
    @RequireRole(UserConstant.UserType.ADMIN)
    public BaseResponse<PageResponse<UserResponse>> listUserByPage(@RequestBody UserQueryRequest userQueryRequest) {
        if (userQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        QueryWrapper<GeneralUser> queryWrapper = new QueryWrapper<>();

        // 添加查询条件
        QueryUtils.addLikeCondition(queryWrapper, "account_name", userQueryRequest.getAccountName());
        QueryUtils.addLikeCondition(queryWrapper, "nick_name", userQueryRequest.getNickName());
        QueryUtils.addLikeCondition(queryWrapper, "email", userQueryRequest.getEmail());
        QueryUtils.addLikeCondition(queryWrapper, "phone_number", userQueryRequest.getPhoneNumber());
        QueryUtils.addEqCondition(queryWrapper, "user_type", userQueryRequest.getUserType());

        // 查询总记录数（包含分页条件）
        Long total = generalUserService.count(queryWrapper);

        // 添加游标分页
        QueryUtils.addCursorPagination(queryWrapper, userQueryRequest.getLastId(), userQueryRequest.getPageSize());

        // 查询用户列表
        List<GeneralUser> userList = generalUserService.list(queryWrapper);
        List<UserResponse> userResponses = UserConverter.toUserResponseList(userList);

        // 获取下一页游标
        Long nextCursor = QueryUtils.getNextCursor(userList);

        // 计算当前页码
        Long current = QueryUtils.calculateCurrentPage(userQueryRequest.getLastId(), userQueryRequest.getPageSize(), total);

        // 构建分页响应
        PageResponse<UserResponse> pageResponse = PageResponse.of(userResponses, current, userQueryRequest.getPageSize().longValue(), total, nextCursor);
        return BaseResponse.success(pageResponse);
    }

    /**
     * 删除用户
     */
    @PostMapping("/delete")
    @Operation(summary = "删除用户", description = "删除用户接口")
    @RequireRole(UserConstant.UserType.ADMIN)
    public BaseResponse<Boolean> deleteUser(@Valid @RequestBody UpdateRequest updateRequest, HttpServletRequest request) {
        if (updateRequest == null || updateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        long id = updateRequest.getId();
        // 校验数据是否存在
        GeneralUser oldUser = generalUserService.getById(id);
        if (oldUser == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        boolean b = generalUserService.removeById(id);
        return BaseResponse.success(b);
    }

    /**
     * 更新用户信息
     */
    @PostMapping("/update")
    @Operation(summary = "更新用户信息", description = "用户更新自己的个人信息")
    @RequireRole(value = {UserConstant.UserType.STUDENT, UserConstant.UserType.MAINTENANCE, UserConstant.UserType.ADMIN}, allowSelf = true)
    public BaseResponse<Boolean> updateUser(@Valid @RequestBody UserUpdateRequest updateRequest, HttpServletRequest request) {
        if (updateRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        Long currentUserId = UserHolder.getCurrentUserId();
        GeneralUser currentUser = UserHolder.getCurrentUser();

        // 更新基本用户信息
        boolean updateSuccess = generalUserService.updateUserInfo(
                currentUserId,
                updateRequest.getNickName(),
                updateRequest.getEmail(),
                updateRequest.getPhoneNumber()
        );

        if (!updateSuccess) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "更新用户信息失败");
        }

        // 如果是学生用户，更新宿舍信息
        if (UserConstant.UserType.STUDENT == currentUser.getUserType() &&
                StrUtil.isNotBlank(updateRequest.getDormitoryName())) {
            boolean dormitoryUpdateSuccess = userStudentService.updateDormitoryName(
                    currentUserId, updateRequest.getDormitoryName());
            if (!dormitoryUpdateSuccess) {
                log.warn("用户 {} 宿舍信息更新失败", currentUserId);
            }
        }

        return BaseResponse.success(true);
    }

    /**
     * 修改密码
     */
    @PostMapping("/update-password")
    @Operation(summary = "修改密码", description = "用户修改自己的密码")
    @RequireRole(value = {UserConstant.UserType.STUDENT, UserConstant.UserType.MAINTENANCE, UserConstant.UserType.ADMIN}, allowSelf = true)
    public BaseResponse<Boolean> updatePassword(@Valid @RequestBody UserPasswordUpdateRequest passwordUpdateRequest, HttpServletRequest request) {
        if (passwordUpdateRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        String oldPassword = passwordUpdateRequest.getOldPassword();
        String newPassword = passwordUpdateRequest.getNewPassword();
        String confirmPassword = passwordUpdateRequest.getConfirmPassword();

        // 验证新密码和确认密码是否一致
        if (!newPassword.equals(confirmPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "新密码和确认密码不一致");
        }

        Long currentUserId = UserHolder.getCurrentUserId();
        boolean updateSuccess = generalUserService.updatePassword(currentUserId, oldPassword, newPassword);

        if (!updateSuccess) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "密码修改失败");
        }

        return BaseResponse.success(true);
    }

    /**
     * 管理员更新用户信息
     */
    @PostMapping("/admin/update")
    @Operation(summary = "管理员更新用户信息", description = "管理员更新用户信息，包括用户类型")
    @RequireRole(UserConstant.UserType.ADMIN)
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> adminUpdateUser(@Valid @RequestBody UserAdminUpdateRequest updateRequest, HttpServletRequest request) {
        if (updateRequest == null || updateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        Long userId = updateRequest.getId();

        // 校验用户是否存在
        GeneralUser existingUser = generalUserService.getById(userId);
        if (existingUser == null) {
            throw new BusinessException(ErrorCode.USER_NOT_EXIST);
        }

        // 如果要更新为学生类型，必须提供宿舍地址
        if (UserConstant.UserType.STUDENT == updateRequest.getUserType() &&
            StrUtil.isBlank(updateRequest.getDormitoryName())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "学生用户必须填写宿舍地址");
        }

        boolean updateSuccess = generalUserService.adminUpdateUserInfo(
                userId,
                updateRequest.getNickName(),
                updateRequest.getEmail(),
                updateRequest.getPhoneNumber(),
                updateRequest.getUserType(),
                updateRequest.getDormitoryName()
        );

        if (!updateSuccess) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "更新用户信息失败");
        }

        return BaseResponse.success(true);
    }
}
